package com.dbf.forum.common.service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.RollbackException;

import org.hibernate.Session;
import org.modelmapper.ModelMapper;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service("commonService")
@Transactional
public abstract class CommonServiceImpl implements CommonService {
//	@Autowired @Qualifier("sessionFactory")
//	@Resource(name="entityManagerFactory")
	@PersistenceContext
	protected EntityManager em;
	static Session session ;
	
	@PostConstruct
	public void init(){
		session = (Session) em.getDelegate();//getEntityManagerFactory().unwrap(Session.class);
		session = session.getSessionFactory().openSession();
	}
	
	public CommonServiceImpl() {
		
	}
	
	private static final ModelMapper INSTANCE = new ModelMapper();
	
	@Transactional
	@SuppressWarnings("unchecked")
	public <T> T getEntity(Class<? extends T> clazz, Serializable id) {
		return (T) session.get(clazz, id);
	}
	@Transactional
	@SuppressWarnings("unchecked")
	public <T> T getEntity(Class<? extends T> clazz,String property, Serializable id) {
		return id==null? null: (T) session.
				createQuery("select clazz from "+clazz.getName()+" as clazz where clazz."+property+"='"+id+"'").list().get(0);
	}
	@SuppressWarnings("unchecked")
	@Transactional
	public <T> T saveEntity(T clazz) {
		Serializable id = session.save(clazz);
		return (T) session.get(clazz.getClass(), id);
	}
	@Transactional
	public void persistEntities() {
		try {
			session.flush();
		} catch (RollbackException rollbackException) {
			rollbackException.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	@SuppressWarnings("unchecked")
	@Transactional
	public <T> List<T> getAllEntities(Class<? extends T> clazz) {
		List<T> list = session.createCriteria(clazz).list();
		return list;
	}
	
	public <S, T> Page<T> mapPage(Page<S> source, Class<T> targetClass) {
        List<S> sourceList = source.getContent();

        List<T> list = new ArrayList<T>();
        
        for (int i = 0; i < sourceList.size(); i++) {
            T target = INSTANCE.map(sourceList.get(i), targetClass);
            list.add(target);
        }
        return new PageImpl<T>(list, new PageRequest(source.getNumber(), source.getSize(), source.getSort()),
                source.getTotalElements());
    }

}
